<cfcomponent name="FusecacheStaticFileManager" hint="">
	
	<cfset variables.instance = {} />
	
	<!--- init() --->
	<cffunction name="init" access="public" output="false" returntype="fusecache.FusecacheStaticFileManager" hint="Creates and returns an instance of the FusecacheStaticFileManager object.">
		<cfargument name="oFusecacheFactory" type="fusecache.FusecacheFactory" required="true" />
		<cfscript>
			variables.instance["fusecacheFactory"] = arguments.oFusecacheFactory;
			variables.instance["files"] = QueryNew("id,path,expires","integer,varchar,date");
			startScheduledTask();
			return this;
		</cfscript>
	</cffunction>
	
	
	<!--- getFiles() --->
	<cffunction name="getFiles" access="public" output="false" returntype="query" hint="Returns the instance query of files on record.">
		<cfreturn variables.instance["files"] />
	</cffunction>
	
	
	<!--- getFusecacheFactory() --->
	<cffunction name="getFusecacheFactory" access="public" output="false" returntype="fusecache.FusecacheFactory" hint="Returns the instance copy of the Fusecache singleton.">
		<cfreturn variables.instance["fusecacheFactory"] />
	</cffunction>
	
	
	<!--- startScheduledTask() --->
	<cffunction name="startScheduledTask" access="private" output="false" returntype="void" hint="Creates a scheduled task (specific to this Application) for the management of expired static files.">
		<cfschedule action="update" task="FusecacheStaticFileManager_App:#application.applicationname#" interval="60" operation="httprequest" startdate="8/22/09" starttime="9:39 PM" url="http://#cgi.server_name#/index.cfm?fuseaction=fusecache.manageStaticFiles" />
	</cffunction>
	
	
	<!--- stopScheduledTask() --->
	<cffunction name="stopScheduledTask" access="private" output="false" returntype="void" hint="Deletes the application-specific scheduled task that cleans up expired files so it doesn't keep running if the application isn't running.">
		<cfschedule action="delete" task="FusecacheStaticFileManager_App:#application.applicationname#" />
	</cffunction>
	
	
	<!--- addFileRecord() --->
	<cffunction name="addFileRecord" access="public" output="false" returntype="void" hint="">
		<cfargument name="filePath" type="string" required="true" />
		<cfargument name="expiration" type="string" required="true" />
		
		<cfset var local = {} />
		<cfset var qTempQuery = getFiles() />
		
		<cfquery name="qLookForPath" dbtype="query">
		SELECT id, path, expires
		FROM qTempQuery
		WHERE path = '#arguments.filePath#'
		</cfquery>
		
		<cfif (qLookForPath.RecordCount)>
			<cfscript>
				QuerySetCell(variables.instance["files"],"expires","#DateAdd("s",arguments.expiration,Now())#",qLookForPath.id);
			</cfscript>
		<cfelse>
			<cfscript>
				local.nNewRowCount = QueryAddRow(variables.instance["files"],1);
				QuerySetCell(variables.instance["files"],"id","#(variables.instance["files"].RecordCount)#",local.nNewRowCount);
				QuerySetCell(variables.instance["files"],"path","#arguments.filePath#",local.nNewRowCount);
				QuerySetCell(variables.instance["files"],"expires","#DateAdd("s",arguments.expiration,Now())#",local.nNewRowCount);
			</cfscript>
		</cfif>
	</cffunction>
	
	
	<!--- deleteFiles() --->
	<cffunction name="deleteFiles" access="public" output="false" returntype="void" hint="">
		<cfargument name="mode" type="string" required="false" default="expired" />
		<cfset var local = {} />
		<cfset var qTempQuery = getFiles() />
		<cfset local.time = Now() />
		
		<!--- Look for files that have expired --->
		<cfquery name="qLookForExpiredFiles" dbtype="query">
		SELECT id, path
		FROM qTempQuery
		<cfif (arguments.mode EQ "expired")>WHERE expires < #local.time#</cfif>
		</cfquery>
		
		<!--- Check for results, if found loop over them and delete the files in those paths --->
		<cfif (qLookForExpiredFiles.RecordCount)>
			<cfloop query="qLookForExpiredFiles">
				<cftry>
					<cfset FileDelete(ExpandPath(qLookForExpiredFiles.path)) />
					<cfset QuerySetCell(variables.instance["files"],"expires","",qLookForExpiredFiles.id) />
					
					<!--- See how many folders deep this file was (assume initial /) --->
					<cfset local.sStartingFolder = GetDirectoryFromPath(qLookForExpiredFiles.path) />
					<cfset local.nFoldersDeep = ListLen(local.sStartingFolder,"/") />
					<cfset local.sFolderList = "">
					
					<!--- Loop over the folders by parsing down the path each time --->
					<cfloop from="1" to="#local.nFoldersDeep#" index="i">
						
						<!--- Folder backstepping magic --->
						<cfset local.sCurrentFolder = "" />
						<cfloop from="1" to="#((local.nFoldersDeep+1)-i)#" index="x">
							<cfset local.sCurrentFolder = local.sCurrentFolder & "/" & ListGetAt(local.sStartingFolder,x,"/") />
						</cfloop>
						
						<!--- Attemp to delete --->
						<cfdirectory action="list" directory="#ExpandPath(local.sCurrentFolder)#" name="local.qDirList" />
						<cfif (local.qDirList.RecordCount EQ 0)>
							<cfdirectory action="delete" directory="#ExpandPath(local.sCurrentFolder)#" />
						</cfif>
						
					</cfloop>
					
					<cfcatch type="any">
						<cfthrow type="fusecache.StaticFileManagement" message="#cfcatch.message#" />
					</cfcatch>
				</cftry>
			</cfloop>
		</cfif>
	</cffunction>
	
	
	<!--- saveFileData() --->
	<cffunction name="saveFileData" access="private" output="false" returntype="void" hint="">
		<cfset var local = {} />
		<cfset var qTempQuery = getFiles() />
		
		<!--- Get file data that has expiration data is not blank string --->
		<cfif (qTempQuery.RecordCount GT 0)>
			
			<!--- Query for rows that have a expiration data that's not empty --->
			<!--- (Because we can't programmatically remove query rows, we set the expiration to blank --->
			<cfquery name="qGetWriteOutData" dbtype="query">
			SELECT id, path, expires
			FROM qTempQuery
			WHERE expires != ''
			</cfquery>
			
			<!--- Create data to write out --->
			<cfsavecontent variable="local.FileOutput"><cfoutput>
<cfloop query="qGetWriteOutData">#qGetWriteOutData.id#,#qGetWriteOutData.path#,#qGetWriteOutData.expires#
</cfloop></cfoutput>
			</cfsavecontent>
			
			<!--- Create the path and write the file to the file system --->
			<cfset local.sOutputFilePath = ExpandPath(GetDirectoryFromPath(variables.instance["fusecacheFactory"].getConfigFilePath())) & "/fusecache_static_file_data.csv" />
			<cfset FileWrite(local.sOutputFilePath,local.FileOutput) />
		</cfif>
		
		
	</cffunction>
	
	
	<!--- shutdown() --->
	<cffunction name="shutdown" access="public" output="false" returntype="void" hint="">
		<!--- Look to see if the user wants to delete all files when the application ends --->
		<cfif (variables.instance["fusecacheFactory"].getDeleteAllStaticFilesOnApplicationEnd())>
			<!--- Delete all files --->
			<cfset deleteFiles("all") />
		<cfelse>
			<!--- The user does not want to delete all files. Save a copy of the current query to disk. We'll reload it when the app starts again. --->
			<cfset saveFileData() />
		</cfif>
	</cffunction>

	
</cfcomponent>